namespace ScrumSprintMonitor.ConfigEditor
{
	#region #using Directives

	using System;
	using System.Collections.Generic;
	using System.ComponentModel.Composition;
	using System.ComponentModel.Composition.Hosting;
	using System.Diagnostics;
	using System.IO;
	using System.Linq;
	using System.Reflection;
	using System.Windows;

	using Implementation;

	using Infrastructure;

	using Microsoft.Practices.ServiceLocation;

	using Ninject.Core;

	using UI.Wpf;

	using Views.ConfigurationView;

	#endregion

	public class Bootstrapper
	{
		private readonly Assembly assembly = Assembly.GetExecutingAssembly();
		private CompositionContainer container;
		private NinjectContainerAbstraction ninjectContainerAbstraction;

		[ImportMany(typeof(IModule))]
		public List<IModule> AdditionalKernelModules { get; set; }

		public void Run()
		{
			DesignerProperties.GetIsInDesignMode = (object x) => StubDesignerProperties.GetIsInDesignMode(null);

			this.ninjectContainerAbstraction = NinjectContainerAbstraction.EnsureContainerIsSetUp();
			NinjectContainerAbstraction.RegisterModule<NinjectAppRuntimeModule>();
			this.ninjectContainerAbstraction.LoadRegisteredModules(false);

			if (Compose())
			{
				this.ninjectContainerAbstraction.Instance.Load(AdditionalKernelModules);

				var kernel = ServiceLocator.Current.GetInstance<IKernel>();

				var model = kernel.Get<IConfigurationViewModel>();
				var optionsDialog = new ConfigurationWindow(model);
				if (optionsDialog.ShowDialog().GetValueOrDefault(false))
				{
					if (!Settings.Default.IsReadOnly)
					{
						Settings.Default.Save();
					}

					Application.Current.Shutdown(1);
					return;
				}
			}

			Application.Current.Shutdown(0);
		}

		private bool Compose()
		{
			//this.logger.Debug("Composing MEF container...");

			var aggregateCatalog = new AggregateCatalog();
			string binFolder = Path.GetDirectoryName(this.assembly.Location);
			//string addInsBinFolder = Path.Combine(binFolder, @"AddIns");
			string serverAdaptersBinFolder = Path.Combine(binFolder, @"AddIns\ServerAdapters");

			AddCatalogFromFolderPath(aggregateCatalog, serverAdaptersBinFolder);
			//AddCatalogFromFolderPath(aggregateCatalog, addInsBinFolder);

			//this.logger.Debug("Found {0} parts in {1} MEF catalogs:", aggregateCatalog.Parts.Count(), aggregateCatalog.Catalogs.Count);
			Debug.Assert(aggregateCatalog.Parts.Any());

			this.container = new CompositionContainer(aggregateCatalog);

			var batch = new CompositionBatch();
			batch.AddPart(this);
			batch.AddPart(ServiceLocator.Current.GetInstance<IProcessTemplateAdapterProvider>());
			batch.AddExportedValue(ServiceLocator.Current.GetInstance<IServiceProvider>());

			try
			{
				this.container.Compose(batch);
			}
			catch (CompositionException compositionException)
			{
				//this.logger.Fatal(compositionException, "Found exception while composing MEF container.");

				MessageBox.Show(compositionException.ToString());
				return false;
			}

			return true;
		}

		private static void AddCatalogFromFolderPath(AggregateCatalog aggregateCatalog, string binFolder)
		{
			if (Directory.Exists(binFolder))
			{
				//this.logger.Debug("Creating MEF DirectoryCatalog from {0}...", binFolder);

				var addinsDirectoryCatalog = new DirectoryCatalog(binFolder);
				aggregateCatalog.Catalogs.Add(addinsDirectoryCatalog);

				foreach (var part in addinsDirectoryCatalog.Parts)
				{
					//this.logger.Debug("{0}", part.ToString());
				}
			}
			else
			{
				//this.logger.Debug("{0} addin folder not found.", binFolder);
			}
		}
	}
}